package com.gobang.modules.room;

import com.gobang.proto.GameProto.*;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 房间实体（包含游戏逻辑）
 */
@Data
public class Room {
    private static final int BOARD_SIZE = 15;
    
    /** 房间ID（同时作为游戏ID） */
    private String roomId;
    
    /** 黑方玩家ID */
    private Long blackPlayerId;
    
    /** 黑方玩家名称 */
    private String blackPlayerName;
    
    /** 白方玩家ID */
    private Long whitePlayerId;
    
    /** 白方玩家名称 */
    private String whitePlayerName;
    
    /** 房间状态 */
    private RoomStatus status;
    
    /** 创建时间 */
    private LocalDateTime createTime;
    
    /** 游戏开始时间 */
    private LocalDateTime startTime;
    
    /** 游戏结束时间 */
    private LocalDateTime endTime;
    
    /** 棋盘 */
    private PieceColor[][] board;
    
    /** 当前回合 */
    private PieceColor currentTurn;
    
    /** 移动次数 */
    private int moveCount;
    
    /** 游戏结果 */
    private GameResult result;
    
    /** 胜者ID */
    private Long winnerId;
    
    /** 获胜位置 */
    private List<WinPosition> winPositions;
    
    public Room(String roomId, Long blackPlayerId, String blackPlayerName,
                Long whitePlayerId, String whitePlayerName) {
        this.roomId = roomId;
        this.blackPlayerId = blackPlayerId;
        this.blackPlayerName = blackPlayerName;
        this.whitePlayerId = whitePlayerId;
        this.whitePlayerName = whitePlayerName;
        this.status = RoomStatus.WAITING;
        this.createTime = LocalDateTime.now();
        this.winPositions = new ArrayList<>();
        
        // 初始化棋盘
        this.board = new PieceColor[BOARD_SIZE][BOARD_SIZE];
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                board[i][j] = PieceColor.NONE;
            }
        }
        this.currentTurn = PieceColor.BLACK;
        this.moveCount = 0;
    }
    
    /**
     * 开始游戏
     */
    public void startGame() {
        this.status = RoomStatus.PLAYING;
        this.startTime = LocalDateTime.now();
    }
    
    /**
     * 结束游戏
     */
    public void endGame() {
        this.status = RoomStatus.FINISHED;
        this.endTime = LocalDateTime.now();
    }
    
    /**
     * 检查玩家是否在房间中
     */
    public boolean containsPlayer(Long playerId) {
        return blackPlayerId.equals(playerId) || whitePlayerId.equals(playerId);
    }
    
    /**
     * 落子
     */
    public boolean placePiece(int row, int col, Long playerId) {
        // 验证位置
        if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE) {
            return false;
        }
        
        // 验证是否已有棋子
        if (board[row][col] != PieceColor.NONE) {
            return false;
        }
        
        // 验证是否轮到该玩家
        if (currentTurn == PieceColor.BLACK && !playerId.equals(blackPlayerId)) {
            return false;
        }
        if (currentTurn == PieceColor.WHITE && !playerId.equals(whitePlayerId)) {
            return false;
        }
        
        // 落子
        board[row][col] = currentTurn;
        moveCount++;
        
        // 检查是否获胜
        if (checkWin(row, col)) {
            result = currentTurn == PieceColor.BLACK ? GameResult.BLACK_WIN : GameResult.WHITE_WIN;
            winnerId = currentTurn == PieceColor.BLACK ? blackPlayerId : whitePlayerId;
            return true;
        }
        
        // 检查是否平局
        if (moveCount >= BOARD_SIZE * BOARD_SIZE) {
            result = GameResult.DRAW;
            return true;
        }
        
        // 切换回合
        currentTurn = currentTurn == PieceColor.BLACK ? PieceColor.WHITE : PieceColor.BLACK;
        
        return true;
    }
    
    /**
     * 检查是否获胜
     */
    private boolean checkWin(int row, int col) {
        PieceColor color = board[row][col];
        
        // 检查四个方向
        if (checkDirection(row, col, 1, 0, color) ||   // 水平
            checkDirection(row, col, 0, 1, color) ||   // 垂直
            checkDirection(row, col, 1, 1, color) ||   // 斜线1
            checkDirection(row, col, 1, -1, color)) {  // 斜线2
            return true;
        }
        
        return false;
    }
    
    /**
     * 检查指定方向是否有五子连珠
     */
    private boolean checkDirection(int row, int col, int dRow, int dCol, PieceColor color) {
        int count = 1;
        List<WinPosition> positions = new ArrayList<>();
        positions.add(WinPosition.newBuilder().setRow(row).setCol(col).build());
        
        // 正方向
        for (int i = 1; i < 5; i++) {
            int newRow = row + i * dRow;
            int newCol = col + i * dCol;
            if (newRow < 0 || newRow >= BOARD_SIZE || newCol < 0 || newCol >= BOARD_SIZE) {
                break;
            }
            if (board[newRow][newCol] == color) {
                count++;
                positions.add(WinPosition.newBuilder().setRow(newRow).setCol(newCol).build());
            } else {
                break;
            }
        }
        
        // 反方向
        for (int i = 1; i < 5; i++) {
            int newRow = row - i * dRow;
            int newCol = col - i * dCol;
            if (newRow < 0 || newRow >= BOARD_SIZE || newCol < 0 || newCol >= BOARD_SIZE) {
                break;
            }
            if (board[newRow][newCol] == color) {
                count++;
                positions.add(WinPosition.newBuilder().setRow(newRow).setCol(newCol).build());
            } else {
                break;
            }
        }
        
        if (count >= 5) {
            this.winPositions = positions;
            return true;
        }
        
        return false;
    }
    
    /**
     * 投降
     */
    public void surrender(Long playerId) {
        result = GameResult.SURRENDER_RESULT;
        if (playerId.equals(blackPlayerId)) {
            winnerId = whitePlayerId;
        } else {
            winnerId = blackPlayerId;
        }
    }
    
    /**
     * 获取当前回合的玩家ID
     */
    public Long getCurrentPlayerId() {
        return currentTurn == PieceColor.BLACK ? blackPlayerId : whitePlayerId;
    }
    
    /**
     * 获取玩家颜色
     */
    public PieceColor getPlayerColor(Long playerId) {
        if (playerId.equals(blackPlayerId)) {
            return PieceColor.BLACK;
        } else if (playerId.equals(whitePlayerId)) {
            return PieceColor.WHITE;
        }
        return PieceColor.NONE;
    }
    
    /**
     * 游戏是否结束
     */
    public boolean isGameOver() {
        return result != null && result != GameResult.UNKNOWN_RESULT;
    }
    
    /**
     * 获取游戏ID（使用房间ID作为游戏ID）
     */
    public String getGameId() {
        return roomId;
    }
}
